package Abstract_Factory

import "fmt"

/**
http://c.biancheng.net/view/1351.html
- (不足)工厂方法模式只考虑生产同等级的产品
- 抽象工厂模式，将考虑多等级产品的生产，将同一个具体工厂所产生的位于不同等级的一组产品称为一个产品族
	- (优点)添加新产品时，添加新产品的实现和生产新产品的工厂即可，对之前的产品及工厂不影响
*/

// <Product>
// 定义了产品的规范，描述了产品的主要特性和功能，抽象工厂模式有多个抽象产品
type Lunch interface {
	Cook()
}

// <ConcreteProduct> 具体产品1_SmallRise，是简单工厂模式的创建目标
type SmallRise struct {
}

// <ConcreteProduct> 具体产品1_SmallTomato，是简单工厂模式的创建目标
type SmallTomato struct {
}

func (r *SmallRise) Cook() {
	fmt.Println("it is small rise.")
}
func (t *SmallTomato) Cook() {
	fmt.Println("it is small Tomato.")
}

// <Abstract_Factory> 抽象工厂
// 提供了创建产品的接口，它包含多个创建产品的方法(New...)，可以创建多个不同等级的产品
type LunchFactory interface {
	CreateFood() Lunch
	CreateVegetable() Lunch
}

// <Concrete Factory> 具体工厂1，SmallLunchFactory
// 实现了抽象工厂中的多个抽象方法，完成具体产品的创建
type SmallLunchFactory struct {
}

func NewSmallLunchFactory() LunchFactory {
	return &SmallLunchFactory{}
}

func (s *SmallLunchFactory) CreateFood() Lunch {
	return &SmallRise{}
}

func (s *SmallLunchFactory) CreateVegetable() Lunch {
	return &SmallTomato{}
}

type BigRise struct {
}

// 具体产品2
func (b *BigRise) Cook() {
	fmt.Println("it is big rise")
}

type BigTomato struct {
}

func (b *BigTomato) Cook() {
	fmt.Println("it is big tomato")
}

type BigLunchFactory struct {
}

// <Concrete Factory> 具体工厂2，SmallLunchFactory
func NewBigLaunchFactory() LunchFactory {
	return &BigLunchFactory{}
}
func (big *BigLunchFactory) CreateFood() Lunch {
	return &BigRise{}
}
func (big *BigLunchFactory) CreateVegetable() Lunch {
	return &BigTomato{}
}
